package com.yilin.tms.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yilin.commons.util.ArrayUtil;
import com.yilin.commons.util.JsonUtil;
import com.yilin.tms.core.application.ReturnData;
import com.yilin.tms.core.entity.system.system.Menu;
import com.yilin.tms.core.entity.system.system.MenuOperate;
import com.yilin.tms.core.entity.user.UserType;
import com.yilin.tms.core.entity.user.grant.GrantRoleMenu;
import com.yilin.tms.core.entity.user.grant.GrantRoleMenuOperate;
import com.yilin.tms.core.remote.ISystemRemote;
import com.yilin.tms.user.service.IGrantMenuService;
import com.yilin.tms.user.service.IGrantRoleMenuService;
import com.yilin.tms.user.mapper.GrantRoleMenuMapper;
import com.yilin.tms.user.mapper.GrantRoleMenuOperateMapper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

@Service
public class GrantRoleMenuService extends ServiceImpl<GrantRoleMenuMapper, GrantRoleMenu> implements IGrantRoleMenuService {

    @Resource
    private GrantRoleMenuMapper grantRoleMenuMapper;
    @Resource
    private GrantRoleMenuOperateMapper grantRoleMenuOperateMapper;

    @Resource
    private ISystemRemote systemRemote;
    @Resource
    private IGrantMenuService grantMenuService;

    /**
     * 获取只属于当前用户的菜单
     * */
    @Override
    public List<Menu> getMenuListByUserTypeAndCodes(UserType userType, List<String> grantCodeList) {
        if (grantCodeList==null || grantCodeList.size() == 0) return new ArrayList<>();
        ReturnData<List<Menu>> returnData = systemRemote.getMenuListByUserTypeAndCodes(userType,String.join(",",grantCodeList));
        if (returnData==null) return new ArrayList<>();
        return returnData.getData();
    }

    @Override
    public Map<String, ArrayList<MenuOperate>> getMenuOperateListByCodes(Map<String, String[]> menuCodeOperateCodes) {
        if (menuCodeOperateCodes==null || menuCodeOperateCodes.size() == 0) return new HashMap<>();
        ReturnData<Map<String, ArrayList<MenuOperate>>> returnData = systemRemote.getMenuOperateListMapByCodes(JsonUtil.objectToJson(menuCodeOperateCodes));
        if (returnData==null) return new HashMap<>();
        return returnData.getData();
    }

    /**
     * 公共调取
     * 自动封装菜单权限及其操作权限
     * 获取对应角色的菜单及其操作信息
     * */
    @Override
    public List<Menu> getGrantRoleMenuOperateList(UserType userType, String roleId){
        List<Menu> menuList;
        if (userType == UserType.adminUser) menuList = grantMenuService.getAllMenuList();
        else menuList = getGrantRoleMenuList(userType, roleId);
        //### 获取对应菜单CODE集合
        List<String> menuCodeList = ArrayUtil.fieldAdd(menuList, Menu::getCode);
        //### 获取对应菜单CODE---ADMIN 所有按钮权限
        Map<String, ArrayList<MenuOperate>> allMenuOperateListMap = grantMenuService.getMenuOperateListByMenuCodes(menuCodeList.toArray(new String[]{}));
        //### 获取对应菜单CODE---当前按钮权限
        Map<String, ArrayList<MenuOperate>> grantMenuOperateListMap = getGrantRoleMenuOperateList(roleId, menuCodeList.toArray(new String[]{}));
        //### 封装列表
        for (Menu menu : menuList) {
            List<MenuOperate> operateList;
            if (menu.getCode()==null) continue;
            if (userType == UserType.adminUser) operateList = allMenuOperateListMap.get(menu.getCode());
            else operateList = grantMenuOperateListMap.get(menu.getCode());
            menu.setMenuOperateList(operateList);
        }
        return menuList;
    }

    /**
     * 获取用户菜单列表
     * */
    @Override
    public List<Menu> getGrantRoleMenuList(UserType userType, String roleId) {
        List<String> grantCodeList = getGrantRoleMenuCodeList(roleId);
        return getMenuListByUserTypeAndCodes(userType,grantCodeList);
    }

    /**
     * 获取用户菜单按钮权限列表
     * */
    @Override
    public Map<String, ArrayList<MenuOperate>> getGrantRoleMenuOperateList(String roleId, String[] menuCodes) {
        Map<String,String[]> arrayListMap = new HashMap<>();
        for (String menuCode : menuCodes) {
            List<String> grantCodeList = getGrantRoleMenuOperateCodeList(roleId, menuCode);
            arrayListMap.put(menuCode, grantCodeList.toArray(new String[]{}));
        }
        return getMenuOperateListByCodes(arrayListMap);
    }

    /**
     * 获取用户授权ID列表
     * */
    @Override
    public List<String> getGrantRoleMenuCodeList(String roleId) {
        return grantRoleMenuMapper.getGrantRoleMenuCodeList(roleId);
    }

    /**
     * 获取用户授权ID列表
     * */
    @Override
    public List<String> getGrantRoleMenuOperateCodeList(String roleId, String menuCode) {
        return grantRoleMenuOperateMapper.getGrantRoleMenuOperateCodeList(roleId,menuCode);
    }

    /**
     * 更新权限: 初始化管理员角色授权
     * */
    @Override
    public void initGrantRoleMenuList(String roleId,String memberTypeId) {
        List<String> menuCodeList = grantMenuService.getGrantMenuCodeList(memberTypeId);
        Map<String, String[]> authorityMap = new HashMap<>();
        for (String menuCode : menuCodeList) {
            List<String> operateCodeList = grantMenuService.getGrantMenuOperateCodeList(memberTypeId, menuCode);
            authorityMap.put(menuCode,operateCodeList.toArray(new String[]{}));
        }
        updateGrantRoleMenuList(roleId, authorityMap);
    }

    /**
     * 更新权限
     * */
    @Override
    public void updateGrantRoleMenuList(String roleId, Map<String, String[]> authorityMap) {
        List<String> grantCodeList = getGrantRoleMenuCodeList(roleId);
        // ### 添加新增的权限
        for (String menuCode : authorityMap.keySet() ) {
            if (!grantCodeList.contains(menuCode)){
                GrantRoleMenu api = new GrantRoleMenu();
                api.setRoleId(roleId);
                api.setMenuCode(menuCode);
                grantRoleMenuMapper.insert(api);
            }
            //操作权限
            List<String> grantOperateCodeList = getGrantRoleMenuOperateCodeList(roleId, menuCode);
            for (String operateCode : authorityMap.get(menuCode)) {
                if (!grantOperateCodeList.contains(operateCode)) {
                    GrantRoleMenuOperate menuOperate = new GrantRoleMenuOperate();
                    menuOperate.setRoleId(roleId);
                    menuOperate.setMenuCode(menuCode);
                    menuOperate.setMenuOperateCode(operateCode);
                    grantRoleMenuOperateMapper.insert(menuOperate);
                }
            }
        }
        // ### 移除失效的权限
        for (String menuCode : grantCodeList ) {
            if (!authorityMap.containsKey(menuCode)){
                removeGrantRoleMenu(roleId,menuCode);
            }
            List<String> grantOperateCodeList = getGrantRoleMenuOperateCodeList(roleId, menuCode);
            for (String grantOperateCode : grantOperateCodeList) {
                if (!Arrays.asList(authorityMap.get(menuCode)).contains(grantOperateCode)) {
                    removeGrantRoleMenuOperate(roleId, menuCode, grantOperateCode);
                }
            }
        }
    }

    @Override
    public void removeGrantRoleMenu(String roleId, String menuCode) {
        QueryWrapper<GrantRoleMenu> wrapper = new QueryWrapper<>();
        wrapper.eq("role_id",roleId);
        wrapper.eq("menu_code",menuCode);
        grantRoleMenuMapper.delete(wrapper);
    }

    @Override
    public void saveRoleMenuOperate(GrantRoleMenuOperate roleMenuOperate) {
        grantRoleMenuOperateMapper.insert(roleMenuOperate);
    }

    @Override
    public void removeGrantRoleMenuOperate(String roleId, String roleMenuCode, String grantOperateCode) {
        QueryWrapper<GrantRoleMenuOperate> wrapper = new QueryWrapper<>();
        wrapper.eq("role_id",roleId);
        wrapper.eq("menu_code",roleMenuCode);
        wrapper.eq("menu_operate_code",grantOperateCode);
        grantRoleMenuOperateMapper.delete(wrapper);
    }

}
